package com.ruoyi.workflow.service.impl;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipInputStream;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.system.service.impl.SysDictTypeServiceImpl;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.ProcessDiagramGenerator;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.workflow.mapper.BpmnInfoMapper;
import com.ruoyi.workflow.domain.BpmnInfo;
import com.ruoyi.workflow.service.IBpmnInfoService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 流程定义信息Service业务层处理
 *
 * @author cxh
 * @date 2022-11-14
 */
@Service
public class BpmnInfoServiceImpl extends ServiceImpl<BpmnInfoMapper, BpmnInfo> implements IBpmnInfoService {
    @Autowired
    private ISysDictTypeService dictTypeService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessDiagramGenerator processDiagramGenerator;


    /**
     * 查询流程定义信息列表
     *
     * @param bpmnInfo 流程定义信息
     * @return 流程定义信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<BpmnInfo> selectBpmnInfoList(BpmnInfo bpmnInfo) {


        return getBaseMapper().selectBpmnInfoList(bpmnInfo);
    }



    @Override
    public void deploy(BpmnInfo bpmnInfo, InputStream bpmnFile) {
        //1.获取流程定义类型标签
        List<SysDictData> dataList = dictTypeService.selectDictDataByType("sys_audit_type");
        for (SysDictData data : dataList) {
            //当前字典的值是否为当前流程类型的值
            if (data.getDictValue().equals(bpmnInfo.getBpmnType())){
                bpmnInfo.setBpmnLabel(data.getDictLabel());
                break;
            }
        }
        //将文件保存到本地磁盘
        //2.调用activiti进行流程部署
        Deployment deploy = null;
        String suffix = FileUtils.getSuffix(bpmnInfo.getResourceName());
        if ("zip".equals(suffix)){
            deploy = repositoryService.createDeployment()
                    .addZipInputStream(new ZipInputStream(bpmnFile))//上传zip格式的文件
                    .name(bpmnInfo.getBpmnLabel())
                    .deploy();
        }else {
            deploy = repositoryService.createDeployment()
                    .addInputStream(bpmnInfo.getResourceName(), bpmnFile)
                    .name(bpmnInfo.getBpmnLabel())
                    .deploy();
        }
        //3.保存部署后的相关属性
        bpmnInfo.setDeploymentId(deploy.getId());
        bpmnInfo.setDeployTime(deploy.getDeploymentTime());
        String key = bpmnInfo.getBpmnType();
        bpmnInfo.setProcessDefinitionKey(key);

        //基于流程定义key查询流程定义对象
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(key)
                .deploymentId(deploy.getId())
                .singleResult();
        if (definition == null){
            throw new ServiceException("流程定义key不正确");
        }
        bpmnInfo.setVersion(Long.parseLong(definition.getVersion()+""));

        //5.保存bpmnInfo对象
        super.save(bpmnInfo);
    }

    @Override
    public BpmnInfo getById(Serializable id) {
        BpmnInfo bpmnInfo = super.getById(id);
        if (bpmnInfo == null){
            throw new ServiceException("参数错误,流程信息不存在");
        }
        return bpmnInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteDefinition(Long[] ids) {
        for (Long id : ids) {
            //1.基于流程信息id查询流程信息对象
            BpmnInfo bpmnInfo =this.getById(id);
            try {
                //2.基于流程信息中的部署id,调用activiti的api来删除部署信息
                repositoryService.deleteDeployment(bpmnInfo.getDeploymentId());
            } catch (Exception e) {
                e.printStackTrace();
                //3.如果删除失败,提示前端有正在进行中的流程,无法删除
                throw new ServiceException("删除失败,当前存在正在进行的审核流程");
            }

        }
        //批量删除bpmnInfo的数据
        return super.removeBatchByIds(Arrays.asList(ids));
    }

    @Override
    public InputStream getResourceByType(Long id, String type) {
        //1.基于流程信息id查询流程信息对象
        BpmnInfo bpmnInfo =this.getById(id);
        //2.基于流程部署id查询流程信息对象
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(bpmnInfo.getDeploymentId())
                .singleResult();
        //3.判断当前类要查询数据的类型
        if ("image".equals(type)){
            if (StringUtils.isNotEmpty(definition.getDiagramResourceName())){
               return repositoryService.getResourceAsStream(bpmnInfo.getDeploymentId(),definition.getDiagramResourceName());
            }else {
                BpmnModel bpmnModel = repositoryService.getBpmnModel(definition.getId());
               return processDiagramGenerator.generateDiagram(
                        bpmnModel,
                        "宋体",
                        "宋体",
                        "宋体"
                );
            }
        }else if ("bpmn".equals(type)) {
            return repositoryService.getResourceAsStream(bpmnInfo.getDeploymentId(),definition.getResourceName());

        }

       throw new ServiceException("当前查看到文件类型不支持");
    }

}
